package com.gitee.sop.layui.adminserver.module.background.admin.util;

import com.gitee.sop.layui.adminserver.module.background.admin.entity.SysMenu;
import com.gitee.sop.layui.adminserver.module.base.util.ObjectUtil;
import com.gitee.sop.layui.adminserver.module.base.util.SqlTreeUtil;
import com.gitee.sop.layui.adminserver.module.base.vo.MenuTreeVo;

import java.util.*;

/**
 * 菜单树转换工具
 *
 * @author: huwei
 * @date: 2020/1/15 16:03
 * @version: 1.0.0
 */
public class SysMenuUtil {

    /**
     * 将菜单列表转换为菜单树列表
     *
     * @param sysMenuList
     * @param rootId
     * @return
     */
    public static List<MenuTreeVo> switchMenuTree(List<SysMenu> sysMenuList, int rootId) {
        Map<Integer, List<SysMenu>> pidToChildrenMap = mergeSameNameAndWrapperParentToChildren(sysMenuList);
        List<MenuTreeVo> treeList = new ArrayList<>(sysMenuList.size());
        //整理菜单树，从根节点开始，即pid 为0
        List<SysMenu> rootMenu = pidToChildrenMap.get(rootId);
        if (rootMenu != null) {
            treeList = wrapperMenuTree(rootMenu, pidToChildrenMap);
        }

        return treeList;
    }

    /**
     * 合并相同名称到父节点
     *
     * @param list 菜单列表
     * @return
     */
    public static List<SysMenu> mergeSameParent(List<SysMenu> list) {
        List<SysMenu> res = new ArrayList<>(list.size());
        mergeSameNameAndWrapperParentToChildren(list).forEach((pid, sysMenuList) -> {
            res.addAll(sysMenuList);
        });
        return res;
    }

    /**
     * 合并相同菜单名称，并封装为父节点id到子节点到映射关系
     *
     * @param list 菜单列表
     * @return
     */
    private static Map<Integer, List<SysMenu>> mergeSameNameAndWrapperParentToChildren(List<SysMenu> list) {
        //整理菜单,做成pid到孩子节点的list映射，为做菜单树准备
        Map<Integer, List<SysMenu>> pidToChildrenMap = new HashMap<>(list.size());

        List<Map<String, Object>> treeList = SqlTreeUtil.tree(list);

        treeList.forEach(map -> {
            List<SysMenu> sysMenuList = pidToChildrenMap.get(map.get("pid"));
            if (sysMenuList == null) {
                sysMenuList = new ArrayList<>();
                pidToChildrenMap.put((Integer) map.get("pid"), sysMenuList);
            }
            sysMenuList.add(ObjectUtil.toBean(ObjectUtil.toJson(map), SysMenu.class));
        });

//        //同层级菜单名称与菜单Id的映射，用于合并相同层级相同名称到菜单，避免重复显示；key由pid + name组成
//        Map<String, Integer> sameKeyToIdMap = new HashMap<>(16);
//        //相同名称id转换映射，将为key到id 转为到value到id导航栏下；
//        Map<Integer, Integer> idSwitchMap = new HashMap<>(16);
//        list.forEach(sysMenu -> {
//            //同层级相同菜单预处理数据，已节约集合遍历计算资源；不在本次遍历中统计到原因是：传入集合未按照父节点在前到顺序排序，会导致父节点在子节点顺序之后的子节点被遗漏
//            String key = StringUtil.concat(sysMenu.getPid() ,"#" ,sysMenu.getName());
//            if(sameKeyToIdMap.containsKey(key)){
//                //设置id转换，告知后续子节点，追加在已转化到pid显示
//                idSwitchMap.put(sysMenu.getId() ,sameKeyToIdMap.get(key));
//                return;
//            }
//            sameKeyToIdMap.put(key ,sysMenu.getId());
//
//            //统计父节点和子节点到映射
//            List<SysMenu> children = pidToChildrenMap.get(sysMenu.getPid());
//            if(children == null){
//                children = new ArrayList<>(16);
//                pidToChildrenMap.put(sysMenu.getPid() ,children);
//            }
//            children.add(sysMenu);
//        });
//
//        //相同层级相同父节点合并
//        idSwitchMap.forEach((beSwitchId ,toSwitchId)->{
//            //pid转换
//            pidToChildrenMap.get(beSwitchId).forEach(sysMenu -> {
//                sysMenu.setPid(toSwitchId);
//            });
//            //合并
//            pidToChildrenMap.get(toSwitchId).addAll(pidToChildrenMap.get(beSwitchId));
//            //删除
//            pidToChildrenMap.remove(beSwitchId);
//        });

        //排序
        pidToChildrenMap.forEach((pid, sysMenuList) -> {
            Collections.sort(sysMenuList, (x, y) -> {
                if (x.getSort() > y.getSort()) {
                    return 1;
                } else if (x.getSort() < y.getSort()) {
                    return -1;
                }
                return 0;
            });
        });

        return pidToChildrenMap;
    }

    private static List<MenuTreeVo> wrapperMenuTree(List<SysMenu> sysMenuList, Map<Integer, List<SysMenu>> pidToChildrenMap) {
        List<MenuTreeVo> treeList = new ArrayList<>(sysMenuList.size());
        sysMenuList.forEach(sysMenu -> {
            MenuTreeVo sysMenuTreeVo = new MenuTreeVo(sysMenu.getId(), sysMenu.getName(), sysMenu.getUrl(), sysMenu.getIcon(), sysMenu.getShowMode());
            List<SysMenu> children = pidToChildrenMap.get(sysMenu.getId());
            if (children != null) {
                sysMenuTreeVo.setChildren(wrapperMenuTree(children, pidToChildrenMap));
            }
            treeList.add(sysMenuTreeVo);
        });
        return treeList;
    }
}
